/**
 * @Author: 安广伟
 * @Email: anguangwei@jwzh.tech
 * @Date: 2025-04-06 21:21:26
 * @LastEditTime 2025-04-06 21:21:26
 * @since: 1.0.0
 * @Version: 1.0.0
 * @Description:
 */

package com.hmall.gateway.route;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {


    private final NacosConfigManager nacosConfigManager;

    private final String dataId = "gateway-routes.json";
    private final String group = "DEFAULT_GROUP";

    private final RouteDefinitionWriter writer;

    private final Set<String> routeIds = new HashSet<>();
    @PostConstruct
    public void initRouteConfigListener() throws NacosException {
        // 1、注册监听器并首次拉取配置
        String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }

            @Override
            public void receiveConfigInfo(String configInfo) {
                // 2、监听配置更新
                updateConfigInfo(configInfo);
            }
        });

        // 3、首次启动时，更新一次配置
        updateConfigInfo(configInfo);
    }

    private void updateConfigInfo(String configInfo) {
        log.debug("监听到路由配置变更，{}", configInfo);
        // 反序列化路由配置
        List<RouteDefinition> routeDefinitions  = JSONUtil.toList(configInfo, RouteDefinition.class);

        // 更新之前先删除旧值，否则旧值可能会被保留
        for (String routeId : routeIds){
            writer.delete(Mono.just(routeId)).subscribe();
        }

        // 清空路由id
        routeIds.clear();
        // 判断是否有新的路由要更新
        if (CollUtil.isEmpty(routeDefinitions)){
            return;
        }
        // 更新路由
        for (RouteDefinition routeDefinition : routeDefinitions) {
            writer.save(Mono.just(routeDefinition)).subscribe();
            // 记录路由id，方便下次删除
            routeIds.add(routeDefinition.getId());
        }



    }
}
